package com.example.framework.common.exception.enums;

import com.example.framework.common.exception.ErrorCode;

/**
 * 错误码对象
 * <p>
 * 全局错误码，占用 [0, 999]
 * 一般情况下，使用 HTTP 响应状态码 <a href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status"/>
 * 虽然说，HTTP 响应状态码作为业务使用表达能力偏弱，但是使用在系统层面还是非常不错的
 * 比较特殊的是，因为之前一直使用 0 作为成功，就不使用 200 啦。
 * <p>
 * 业务异常错误码，占用 [1 000 000 000, +∞)
 * 一共 10 位，分成四段
 * 第一段，1 位，类型
 * 1 - 业务级别异常
 * x - 预留
 * 第二段，3 位，系统类型
 * 001 - 用户系统
 * 002 - 商品系统
 * 003 - 订单系统
 * 004 - 支付系统
 * 005 - 优惠劵系统
 * ... - ...
 * 第三段，3 位，模块
 * 不限制规则。
 * 一般建议，每个系统里面，可能有多个模块，可以再去做分段。以用户系统为例子：
 * 001 - OAuth2 模块
 * 002 - User 模块
 * 003 - MobileCode 模块
 * 第四段，3 位，错误码
 * 不限制规则。
 * 一般建议，每个模块自增。
 *
 * @author yuzhenxin
 * @since 2023-08-06
 */
public interface GlobalErrorCodeConstants {

    /* 通用错误码 */

    ErrorCode SUCCESS = new ErrorCode(0, "成功");
    // ========== 客户端错误段 ==========
    ErrorCode BAD_REQUEST = new ErrorCode(400, "请求参数不正确");
    ErrorCode UNAUTHORIZED = new ErrorCode(401, "账号未登录");
    ErrorCode FORBIDDEN = new ErrorCode(403, "没有该操作权限");
    ErrorCode NOT_FOUND = new ErrorCode(404, "请求未找到");
    ErrorCode METHOD_NOT_ALLOWED = new ErrorCode(405, "请求方法不正确");
    ErrorCode LOCKED = new ErrorCode(423, "请求失败，请稍后重试"); // 并发请求，不允许
    ErrorCode TOO_MANY_REQUESTS = new ErrorCode(429, "请求过于频繁，请稍后重试");

    // ========== 服务端错误段 ==========
    ErrorCode INTERNAL_SERVER_ERROR = new ErrorCode(500, "系统异常");
    ErrorCode NOT_IMPLEMENTED = new ErrorCode(501, "功能未实现/未开启");
    ErrorCode REST_CALL_FAILED = new ErrorCode(502, "服务器内部调用错误");
    ErrorCode RESPONSE_TIMEOUT = new ErrorCode(503, "处理请求超时");

    // ========== 自定义错误段 ==========
    ErrorCode REPEATED_REQUESTS = new ErrorCode(900, "重复请求，请稍后重试");
    ErrorCode CUSTOM_ERROR = new ErrorCode(-1, "自定义的错误消息");

    ErrorCode JSON_ERROR = new ErrorCode(1504, "JSON格式化错误");

    /* 以下为常用业务错误码 */

    // ========== 登录注册错误段 ==========
    // AccessToken错误
    ErrorCode LOGIN_ERROR = new ErrorCode(1000, "用户名或密码错误");
    ErrorCode INVALID_ACCESS_TOKEN = new ErrorCode(1001, "无效的AccessToken"); // 非jwt token/secret错误的jwt token，TokenAuthenticationFilter 中不抛出去了，走到后面Spring Security Filter抛出 UNAUTHORIZED
    ErrorCode ACCESS_TOKEN_EXPIRED = new ErrorCode(1002, "AccessToken过期，请尝试续期或重新登录"); // jwt保存过期时间的话，校验时就报错，是不知道是否能续期的
    ErrorCode TOKEN_EXPIRED = new ErrorCode(1003, "AccessToken和RefreshToken过期，请重新登录");
    ErrorCode LOGGED_IN_ON_ANOTHER_DEVICE = new ErrorCode(1004, "当前用户已在其它设备登录，请重新登录");
    ErrorCode BEEN_KICKED_OFFLINE = new ErrorCode(1005, "当前用户已被踢下线，请重新登录");

    // 续期错误
    ErrorCode INVALID_REFRESH_TOKEN = new ErrorCode(1011, "无效的RefreshToken");
    ErrorCode REFRESH_TOKEN_EXPIRED = new ErrorCode(1012, "RefreshToken过期，请重新登录");
    ErrorCode REFRESH_TOKEN_DELETED = new ErrorCode(1003, "此RefreshToken已被禁用，请重新登录"); // 伪造的合法也未过期的token/异地登陆/服务端删除了redis缓存

    ErrorCode USER_NOT_FOUND = new ErrorCode(1100, "用户不存在");
    ErrorCode USER_STATE_ERROR = new ErrorCode(1101, "用户被禁用");
    ErrorCode USER_EXISTS = new ErrorCode(1102, "用户id已存在");

}
